# @Version        : 1.0
# @Update Time    : 2025/10/13 22:39
# @File           : manager.py
# @IDE            : PyCharm
# @Desc           : 文件描述信息
import threading
from typing import ClassVar, Dict, Optional, List

from authx.core.auth_interface import AuthInterface
from authx.core.auth_interface_imp import AuthInterfaceImpl
from authx.core.auth_logic_interface import AuthLogicProtocol
from authx.dao.base import AuthTokenDao
from authx.dao.memory import MemoryAuthDao
from authx.settings.config import (
    AuthConfig,
    LogicOverrides,
    merge_config,
    to_domain_config,
)
from authx.strategy.fa_strategy import AuthStrategy
from authx.utils.singleton import Singleton


class AuthManager(metaclass=Singleton):
    _lock: ClassVar[threading.RLock] = threading.RLock()
    _inited: ClassVar[bool] = False
    _config: ClassVar[Optional[AuthConfig]] = None
    _dao: ClassVar[Optional[AuthTokenDao]] = None
    _auth_imp: ClassVar[Optional[AuthInterface]] = None
    _logic_map: ClassVar[Dict[str, AuthLogicProtocol]] = {}
    _DEFAULT_LOGIN_TYPE: ClassVar[str] = "login"

    def __new__(cls, *a, **kw):
        raise TypeError("AuthManager 是静态管理器，请使用类方法")

    @classmethod
    def init(
        cls,
        *,
        config: Optional[AuthConfig] = None,
        dao: Optional[AuthTokenDao] = None,
        auth_imp: Optional[AuthInterface] = None,
    ):
        if not cls._inited:
            cfg: AuthConfig = config or to_domain_config()
            dao = dao or MemoryAuthDao()
            auth_imp = auth_imp or AuthInterfaceImpl()
            cls._config, cls._dao, cls._auth_imp = cfg, dao, auth_imp
            cls._inited = True

    @classmethod
    def register_login_type(
        cls,
        login_type: str,
        logic_cls: type[AuthLogicProtocol],
        overrides: Optional[LogicOverrides] = None,
        *,
        as_default: bool = False,
    ) -> AuthLogicProtocol:
        if not login_type:
            raise ValueError("login_type 不能为空")
        merged = merge_config(cls._config, overrides)  # type: ignore
        logic = logic_cls(
            login_type=login_type,
            dao=cls._dao,
            config=merged,
            auth_imp=cls._auth_imp,  # type: ignore
        )
        with cls._lock:
            cls._logic_map[login_type] = logic
            if as_default:
                cls._logic_map[cls._DEFAULT_LOGIN_TYPE] = logic
        return logic

    @classmethod
    def put_logic(cls, logic: type[AuthLogicProtocol]) -> None:
        """
        将 logic 添加到 AuthManager 中
        """
        with cls._lock:
            cls._logic_map[logic.login_type] = logic
            cls._logic_map[cls._DEFAULT_LOGIN_TYPE] = logic

    @classmethod
    def remove_logic(cls, login_type: str) -> None:
        """
        从 AuthManager 中移除 logic
        """
        with cls._lock:
            if login_type in cls._logic_map:
                del cls._logic_map[login_type]

    @classmethod
    def get_logic(
        cls, login_type: Optional[str] = None, is_create: bool = True
    ) -> AuthLogicProtocol:
        if not cls._inited:
            raise RuntimeError("AuthManager 未初始化")
        lt = login_type or cls._DEFAULT_LOGIN_TYPE
        logic = cls._logic_map.get(lt)
        if logic is None and is_create:
            return AuthStrategy().create_stp_logic(lt)
        return logic

    @classmethod
    def get_dao(cls) -> AuthTokenDao:
        if cls._dao is None:
            cls._dao = MemoryAuthDao()
        return cls._dao

    @classmethod
    def set_dao(cls, dao: AuthTokenDao):
        cls._dao = dao

    @classmethod
    def get_config(cls) -> AuthConfig:
        if cls._config is None:
            cls._config = to_domain_config()
        return cls._config

    @classmethod
    def get_auth_interface(cls) -> AuthInterface:
        if cls._auth_imp is None:
            cls._auth_imp = AuthInterfaceImpl()
        return cls._auth_imp

    @classmethod
    def set_auth_interface(cls, interface: type[AuthInterface]):
        cls._auth_imp = interface
        print(f"AuthManager 设置权限接口实现 {type(cls._dao)}")

    @classmethod
    def list_login_types(cls) -> List[str]:
        with cls._lock:
            return list(cls._logic_map.keys())

    @classmethod
    def clear(cls):
        with cls._lock:
            cls._inited = False
            cls._config = None
            cls._dao = None
            cls._auth_imp = None
            cls._logic_map.clear()
